import 'transaction_manager.dart';
import 'package:fall_core_base/fall_core_base.dart';
import 'package:fall_core_main/fall_core_main.dart';
import 'package:logger/logger.dart';

/// 事务注解
///
/// 用于标记需要事务支持的方法
class Transactional {
  /// 传播行为
  final TransactionPropagation propagation;

  /// 隔离级别
  final TransactionIsolation isolation;

  /// 超时时间（秒）
  final int timeout;

  /// 是否只读
  final bool readOnly;

  /// 回滚异常类型
  final List<Type> rollbackFor;

  /// 不回滚异常类型
  final List<Type> noRollbackFor;

  /// 事务名称
  final String? name;

  /// 数据库名称
  final String? databaseName;

  const Transactional({
    this.propagation = TransactionPropagation.required,
    this.isolation = TransactionIsolation.defaultLevel,
    this.timeout = -1,
    this.readOnly = false,
    this.rollbackFor = const [],
    this.noRollbackFor = const [],
    this.name,
    this.databaseName,
  });
}

/// 事务 AroundHook - 主要的事务控制逻辑
/// 继承 fall_core 的 AroundHook 接口
class TransactionAroundHook implements AroundHook {
  static final Logger _logger = LoggerFactory.getBusinessLogger();

  @override
  String get name => 'transaction';

  @override
  dynamic execute(HookContext context, Function proceed) {
    try {
      final className = context.target.runtimeType.toString();
      final methodName = context.methodName;

      // 获取 @Transactional 注解（可选）
      final transactionalAnnotation = _getTransactionalAnnotation(context);

      // 检查是否在Froom DAO中
      final isFroomDao = _isFroomDaoMethod(context);

      // 如果既没有注解也不是Froom DAO方法，直接执行
      if (transactionalAnnotation == null && !isFroomDao) {
        return proceed();
      }

      // 如果没有注解，使用默认事务机制
      final definition = transactionalAnnotation != null
          ? _createDefinitionFromAnnotation(transactionalAnnotation)
          : _createDefaultDefinition();

      _logger.d(
        '[$className.$methodName] 开始Froom事务执行',
        error: {
          'className': className,
          'methodName': methodName,
          'hasAnnotation': transactionalAnnotation != null,
          'isFroomDao': isFroomDao,
          'propagation': definition.propagation.name,
          'timestamp': DateTime.now().toIso8601String(),
        },
      );

      // 在事务中执行方法
      return _executeInFroomTransaction(
        context,
        proceed,
        definition,
        className,
        methodName,
      );
    } catch (e) {
      _logger.e('TransactionAroundHook执行异常', error: e);
      // 异常时仍然执行原方法
      return proceed();
    }
  }

  /// 获取 @Transactional 注解（可选）
  Transactional? _getTransactionalAnnotation(HookContext context) {
    try {
      // 这里需要根据 fall_core 的注解获取机制实现
      //TODO: 获取@Transactional注解

      // 暂时返回null，表示没有注解
      return null; // 实际使用时需要实现注解解析
    } catch (e) {
      _logger.w('获取@Transactional注解失败', error: e);
      return null;
    }
  }

  /// 根据注解创建事务定义
  TransactionDefinition _createDefinitionFromAnnotation(
      Transactional annotation) {
    return TransactionDefinition(
      propagation: annotation.propagation,
      isolation: annotation.isolation,
      timeout: annotation.timeout,
      readOnly: annotation.readOnly,
      name: annotation.name,
    );
  }

  /// 创建默认事务定义
  TransactionDefinition _createDefaultDefinition() {
    return const TransactionDefinition(
      propagation: TransactionPropagation.required,
      isolation: TransactionIsolation.defaultLevel,
      timeout: -1,
      readOnly: false,
    );
  }

  /// 检查是否为Froom DAO方法
  bool _isFroomDaoMethod(HookContext context) {
    // 检查类是否有@dao注解或继承自Froom DAO
    // 这里需要根据实际的注解检查机制实现
    final className = context.target.runtimeType.toString();

    // 简单的命名约定检查：以Dao结尾的类名认为是DAO类
    // TODO: 实际项目中应该通过注解检查机制来判断
    return className.endsWith('Dao') || className.contains('Dao');
  }

  /// 在Froom事务中执行方法
  dynamic _executeInFroomTransaction(
    HookContext context,
    Function proceed,
    TransactionDefinition definition,
    String className,
    String methodName,
  ) {
    final transactionManager = TransactionManager.instance;
    final databaseName = _getDatabaseName(context);

    return transactionManager.execute(
      _FroomTransactionCallback(proceed, className, methodName, _logger),
      definition: definition,
      databaseName: databaseName,
    );
  }

  /// 获取数据库名称
  String? _getDatabaseName(HookContext context) {
    final annotation = _getTransactionalAnnotation(context);
    return annotation?.databaseName;
  }
}

/// 事务 ThrowHook - 事务异常时的处理
class TransactionThrowHook implements ThrowHook {
  static final Logger _logger = LoggerFactory.getBusinessLogger();

  @override
  String get name => 'transaction_throw';

  @override
  void execute(HookContext context) {
    try {
      final className = context.target.runtimeType.toString();
      final methodName = context.methodName;
      final exception = context.exception;

      _logger.e(
        '[$className.$methodName] 事务方法执行异常',
        error: {
          'exception': exception,
          'className': className,
          'methodName': methodName,
          'exceptionType': exception?.runtimeType.toString() ?? 'unknown',
          'exceptionMessage': _getSafeExceptionMessage(exception),
          'timestamp': DateTime.now().toIso8601String(),
        },
      );

      // 检查是否需要回滚事务
      _handleTransactionRollback(exception);
    } catch (e) {
      _logger.w('TransactionThrowHook执行异常', error: e);
    }
  }

  /// 安全获取异常消息
  String _getSafeExceptionMessage(dynamic exception) {
    try {
      return exception?.toString() ?? 'null exception';
    } catch (e) {
      return '<异常消息获取失败>';
    }
  }

  /// 处理事务回滚
  void _handleTransactionRollback(dynamic exception) {
    try {
      // 标记事务回滚
      final transactionManager = TransactionManager.instance;
      if (transactionManager.isInTransaction) {
        transactionManager.setRollbackOnly();
        _logger.i('事务已标记为回滚', error: {
          'exception': exception?.runtimeType.toString(),
        });
      }
    } catch (e) {
      _logger.w('事务回滚处理失败', error: e);
    }
  }
}

/// Froom事务回调实现
class _FroomTransactionCallback implements TransactionCallback<dynamic> {
  final Function _proceed;
  final String _className;
  final String _methodName;
  final Logger _logger;

  _FroomTransactionCallback(
      this._proceed, this._className, this._methodName, this._logger);

  @override
  Future<dynamic> doInTransaction(TransactionStatus status) async {
    try {
      _logger.d('Froom事务开始执行', error: {
        'transactionId': status.id,
        'className': _className,
        'methodName': _methodName,
        'sqliteTransaction': status.transaction != null,
      });

      final result = _proceed();

      if (result is Future) {
        final awaitedResult = await result;
        _logger.d('Froom事务执行成功', error: {
          'transactionId': status.id,
          'resultType': awaitedResult?.runtimeType.toString(),
        });
        return awaitedResult;
      }

      _logger.d('Froom事务执行成功', error: {
        'transactionId': status.id,
        'resultType': result?.runtimeType.toString(),
      });
      return result;
    } catch (e) {
      _logger.e('Froom事务执行失败', error: {
        'transactionId': status.id,
        'exception': e,
        'className': _className,
        'methodName': _methodName,
      });

      // 标记事务回滚
      if (!status.isRolledBack) {
        TransactionManager.instance.setRollbackOnly();
      }
      rethrow;
    }
  }
}
